
//
//   Image.cpp
//
//      4.1.07, pm-n.


#include  "Image.h"

#include  <stdlib.h>
#include  <stdio.h>
#include "Utilities.h"

Image::Image( char *file_name_rgb )
{
  FILE  *fp;

  short int  planes;
  short int  bpp;
  char       temp;

  unsigned long  size, i;

  printf( "\n      (Image::Image) loading: %s\n", file_name_rgb );

  if ( (fp = fopen( file_name_rgb, "rb" ) ) == 0 )
    errorAndExit( "(Image::Image) Unknown file name" );

  fseek( fp, 18, SEEK_SET );

  if ( fread( &sizeX, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeX" );
  if ( fread( &sizeY, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeY" );

  if ( fread( &planes, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading planes" );
  if ( planes != 1 )
    errorAndExit( "(Image::Image) wrong no. of planes" );


  if ( fread( &bpp, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading bpp" );
  if ( bpp != 24 )
    errorAndExit( "(Image::Image) wrong no. of bpp" );
 
  channels = 3;

  fseek( fp, 54, SEEK_SET );

  size = sizeX * sizeY;

  if ( ( pixel = (char *)malloc(size*3*sizeof(char)) ) == 0 )
    errorAndExit( "(Image::Image)  error allocating pixels" );

  if ( fread( pixel, size*3, 1, fp ) != 1 )
    errorAndExit( "(Image::Image)  error reading pixels" );

  fclose( fp );

  for ( i=0; i<size; i++ )
    {
      temp         = pixel[3*i];
      pixel[3*i]   = pixel[3*i+2];
      pixel[3*i+2] = temp;
    }

}

Image::Image( char *file_name_rgb, char *file_name_bw )
{
  FILE  *fp;

  short int      planes_rgb, planes_bw;
  short int      bpp_rgb, bpp_bw;
  unsigned long  sizeX_rgb, sizeY_rgb, sizeX_bw, sizeY_bw;
  unsigned long  size, i;
  char           *pixel_rgb,  *pixel_bw;
  int            byte_no, bit_no;

  printf( "\n      (Image::Image)  loading rgb:  %s\n", file_name_rgb );

  if ( (fp = fopen( file_name_rgb, "rb" ) ) == 0 )
    errorAndExit( "(Image::Image) Unknown file name" );

  fseek( fp, 18, SEEK_SET );

  if ( fread( &sizeX_rgb, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeX" );
  if ( fread( &sizeY_rgb, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeY" );

  if ( fread( &planes_rgb, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading planes" );
  if ( planes_rgb != 1 )
    errorAndExit( "(Image::Image) wrong no. of planes" );


  if ( fread( &bpp_rgb, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading bpp" );
  if ( bpp_rgb != 24 )
    errorAndExit( "(Image::Image) wrong no. of bpp" );

  fseek( fp, 54, SEEK_SET );

  size = sizeX_rgb * sizeY_rgb;

  if ( ( pixel_rgb = (char *)malloc(size*3*sizeof(char)) ) == 0 )
    errorAndExit( "(Image::Image)  error allocating rgb pixels" );

  if ( fread( pixel_rgb, size*3, 1, fp ) != 1 )
    errorAndExit( "(Image::Image)  error reading rgb pixels" );

  fclose( fp );


  printf( "\n      (Image::Image)  loading bw:  %s\n", file_name_bw );

  if ( (fp = fopen( file_name_bw, "rb" ) ) == 0 )
    errorAndExit( "(Image::Image) Unknown file name" );

  fseek( fp, 18, SEEK_SET );

  if ( fread( &sizeX_bw, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeX" );
  if ( fread( &sizeY_bw, 4, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading sizeY" );

  if ( fread( &planes_bw, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading planes" );
  if ( planes_bw != 1 )
    errorAndExit( "(Image::Image) wrong no. of planes" );

  if ( (sizeX_rgb != sizeX_bw) || (sizeY_rgb != sizeY_bw) )
    errorAndExit( "(Image::Image) rgb- and bw-pictures are not matching" );

  if ( fread( &bpp_bw, 2, 1, fp ) != 1 )
    errorAndExit( "(Image::Image) error reading bpp" );

  if ( bpp_bw == 8 )
    {
      fseek( fp, 1078, SEEK_SET );
 
      if ( ( pixel_bw = (char *)malloc(size*sizeof(char)) ) == 0 )
        errorAndExit( "(Image::Image)  error allocating bw pixels" );

      if ( fread( pixel_bw, size, 1, fp ) != 1 )
        errorAndExit( "(Image::Image)  error reading bw pixels" );

      fclose( fp );


      if ( ( pixel= (char *)malloc(size*4*sizeof(char)) ) == 0 )
        errorAndExit( "(Image::Image)  error allocating pixels" );

      for ( i=0; i<size; i++ )
        {
          pixel[4*i]   = pixel_rgb[3*i+2];
          pixel[4*i+1] = pixel_rgb[3*i+1];
          pixel[4*i+2] = pixel_rgb[3*i];
          pixel[4*i+3] = pixel_bw[i]; 
        }
    

      channels = 4;

      sizeX = sizeX_rgb;
      sizeY = sizeY_rgb;

      free( pixel_rgb );
      free( pixel_bw );
    }
  else if ( bpp_bw == 1 )
    {

      fseek( fp, 62, SEEK_SET );
 
      if ( ( pixel_bw = (char *)malloc(size/8*sizeof(char)) ) == 0 )
        errorAndExit( "(Image::Image)  error allocating bw pixels" );

      if ( fread( pixel_bw, size/8, 1, fp ) != 1 )
        errorAndExit( "(Image::Image)  error reading bw pixels" );

      fclose( fp );


      if ( ( pixel= (char *)malloc(size*4*sizeof(char)) ) == 0 )
        errorAndExit( "(Image::Image)  error allocating pixels" );

      for ( i=0; i<size; i++ )
        {
          pixel[4*i]   = pixel_rgb[3*i+2];
          pixel[4*i+1] = pixel_rgb[3*i+1];
          pixel[4*i+2] = pixel_rgb[3*i];

          byte_no = i/8;
          bit_no  = i%8;

          if ( ( pixel_bw[byte_no] >> ( 7-bit_no ) ) & 1 ) 
             pixel[4*i+3] = 255;
          else
             pixel[4*i+3] = 0;
    
        }
    

      channels = 4;

      sizeX = sizeX_rgb;
      sizeY = sizeY_rgb;

      free( pixel_rgb );
      free( pixel_bw );
    }

  else
    {
      printf( "\n bpp_bw:  %d\n", bpp_bw ); 
      errorAndExit( "(Image::Image)  unknow value of bpp_bw" );
    }

}


char  *Image::access_pixel()
{
  return pixel;
}


void  Image::get_sizes( unsigned long &sizeX, unsigned long &sizeY )
{
  sizeX = this->sizeX;
  sizeY = this->sizeY;
}


void  Image::get_channels( int &channels )
{
  channels = this->channels;
}



